home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / net3d-0.08 / brain.c < prev    next >
C/C++ Source or Header  |  1995-06-22  |  16KB  |  612 lines

  1. /* brain.c
  2.  *
  3.  * Contains functions for dealing with vehicle brains
  4.  */
  5. #include "net3d.h"
  6.  
  7. /* action and condtion function types.
  8.  */
  9. typedef Bool (*c_func)(struct vehicle *, struct vehicle **,
  10.                struct object **);
  11. typedef void (*a_func)(struct vehicle *, struct vehicle **,
  12.                struct object **);
  13.  
  14. double objectdist(struct object *, struct object *);
  15. struct object *objectahead(struct vehicle *, struct object *,
  16.                Bool (*)(struct object *));
  17.  
  18. /* interesting function prototypes.
  19.  */
  20. static Bool isthreat(struct object *);
  21. static Bool istree(struct object *);
  22. static Bool isany(struct object *);
  23. static Bool isprize(struct object *);
  24.  
  25. /* action and condtion function prototypes.
  26.  */
  27. /* conditions */
  28. static Bool hplow(struct vehicle *, struct vehicle **, struct object **);
  29. static Bool ammolow(struct vehicle *, struct vehicle **, struct object **);
  30. static Bool threatfar(struct vehicle *, struct vehicle **, struct object **);
  31. static Bool treefar(struct vehicle *, struct vehicle **, struct object **);
  32. static Bool anyfar(struct vehicle *, struct vehicle **, struct object **);
  33. static Bool threatclose(struct vehicle *, struct vehicle **, struct object **);
  34. static Bool treeclose(struct vehicle *, struct vehicle **, struct object **);
  35. static Bool anyclose(struct vehicle *, struct vehicle **, struct object **);
  36. static Bool underfire(struct vehicle *, struct vehicle **, struct object **);
  37. static Bool reload(struct vehicle *, struct vehicle **, struct object **);
  38. static Bool reslow(struct vehicle *, struct vehicle **, struct object **);
  39. static Bool moving(struct vehicle *, struct vehicle **, struct object **);
  40. static Bool stall(struct vehicle *, struct vehicle **, struct object **);
  41. static Bool altlow(struct vehicle *, struct vehicle **, struct object **);
  42. static Bool above(struct vehicle *, struct vehicle **, struct object **);
  43. static Bool below(struct vehicle *, struct vehicle **, struct object **);
  44. static Bool always(struct vehicle *, struct vehicle **, struct object **);
  45. static Bool prizefar(struct vehicle *, struct vehicle **, struct object **);
  46. static Bool prizeclose(struct vehicle *, struct vehicle **, struct object **);
  47. static Bool maybe(struct vehicle *, struct vehicle **, struct object **);
  48. static Bool counting(struct vehicle *, struct vehicle **, struct object **);
  49. static Bool collision(struct vehicle *, struct vehicle **, struct object **);
  50.  
  51. /* actions */
  52. static void noop(struct vehicle *, struct vehicle **, struct object **);
  53. static void shoot(struct vehicle *, struct vehicle **, struct object **);
  54. static void stop(struct vehicle *, struct vehicle **, struct object **);
  55. static void accel(struct vehicle *, struct vehicle **, struct object **);
  56. static void decel(struct vehicle *, struct vehicle **, struct object **);
  57. static void left(struct vehicle *, struct vehicle **, struct object **);
  58. static void right(struct vehicle *, struct vehicle **, struct object **);
  59. static void climb(struct vehicle *, struct vehicle **, struct object **);
  60. static void dive(struct vehicle *, struct vehicle **, struct object **);
  61. static void detonate(struct vehicle *, struct vehicle **, struct object **);
  62. static void wall(struct vehicle *, struct vehicle **, struct object **);
  63. static void mine(struct vehicle *, struct vehicle **, struct object **);
  64. static void gunsite(struct vehicle *, struct vehicle **, struct object **);
  65. static void starttimer(struct vehicle *, struct vehicle **, struct object **);
  66.  
  67. static char *conditionnames[CONDITIONCOUNT] = { "hplow","ammolow","threatfar",
  68.                         "treefar","anyfar",
  69.                         "threatclose","treeclose",
  70.                         "anyclose","underfire",
  71.                         "reload","reslow","moving",
  72.                         "stall","altlow","above",
  73.                         "below","always","prizefar",
  74.                         "prizeclose","maybe",
  75.                         "counting","collision"};
  76.  
  77. static char *actionnames[ACTIONCOUNT] ={"noop","shoot","stop","accel",
  78.                     "decel","left","right","climb",
  79.                     "dive","detonate","wall","mine",
  80.                     "gunsite","starttimer"};
  81.  
  82. static c_func conditionfuncs[CONDITIONCOUNT] = {
  83.                 hplow,ammolow,threatfar,treefar,anyfar,
  84.                 threatclose,treeclose,anyclose,
  85.                 underfire,reload,reslow,moving,stall,
  86.                 altlow,above,below,always,prizefar,
  87.                 prizeclose,maybe,counting,collision,
  88.                 };
  89.  
  90. static a_func actionfuncs[ACTIONCOUNT] = {
  91.                 noop,shoot,stop,accel,decel,left,right,
  92.                  climb,dive,detonate,wall,mine,gunsite,
  93.                 starttimer,
  94.                 };
  95.  
  96. /* readbrain - called by readfile() to parse a brain { } section
  97.  * for a vehicle.
  98.  */
  99. void readbrain(struct vehicle *nv, int fp)
  100. {
  101. char tok[256];
  102. Bool donebrain = False;
  103.  
  104. while(!donebrain) {
  105.     ntoken(fp,tok);
  106.     if (!strcmp(tok,"state")) {
  107.         /* Read info about one state
  108.          */
  109.         struct state *st;
  110.         int i;
  111.         Bool donestate = False;
  112.  
  113.         if (nv->stcount > MAX_STATES_PER_VEHICLE)
  114.             fileerror("Maximum number of states exceeded","",fp);
  115.         st = &(nv->states[nv->stcount]);
  116.  
  117.         /* Init state */
  118.         st->action = 0;
  119.         st->lcount = 0;
  120.         st->links  = calloc(MAX_LINKS_PER_STATE,sizeof(struct link));
  121.  
  122.         /* Read state number */
  123.         ntoken(fp,tok);
  124.         st->num = atoi(tok);
  125.         for(i=0; i<nv->stcount; i++)
  126.             if (nv->states[i].num == st->num)
  127.                 fileerror("Duplicate state number",tok,fp);
  128.  
  129.         nv->stcount++;
  130.         if (nv->currentstate == -1)
  131.             nv->currentstate = st->num;
  132.  
  133.         /* Read curly bracket */
  134.         ntoken(fp,tok);
  135.  
  136.         while(!donestate) {
  137.             ntoken(fp,tok);
  138.             if (!strcmp(tok,"action")) {
  139.                 /* Read one action */
  140.                 int ac;
  141.  
  142.                 ntoken(fp,tok);
  143.                 for(ac=0; ac<ACTIONCOUNT; ac++)
  144.                     if (!strcmp(actionnames[ac],tok))
  145.                         break;
  146.                 if (ac == ACTIONCOUNT)
  147.                     fileerror("Action does not exist",
  148.                           tok,fp);
  149.                 st->action |= 1<<ac;
  150.                 }
  151.             else if (!strcmp(tok,"link")) {
  152.                 /* Read one state to state link */
  153.                 struct link *lk;
  154.  
  155.                 lk = &(st->links[st->lcount]);
  156.                 st->lcount++;
  157.  
  158.                 ntoken(fp,tok);        /* read link info */
  159.                 lk->st = atoi(tok);
  160.                 lk->cond = 0;
  161.                 lk->mask = 0;
  162.  
  163.                 ntoken(fp,tok);        /* read { */
  164.  
  165.                 do {
  166.                     int co;
  167.                     char *cname;
  168.  
  169.                     /* Read a condition name, and check
  170.                      * if it is a negative, and if it
  171.                      * actually exists.
  172.                      */
  173.                     ntoken(fp,tok);
  174.                     if (tok[0] == '!')
  175.                         cname = &tok[1];
  176.                     else
  177.                         cname = tok;
  178.  
  179.                     for(co=0; co<CONDITIONCOUNT; co++)
  180.                         if (!strcmp(cname,
  181.                                 conditionnames[co]))
  182.                             break;
  183.                     if (co == CONDITIONCOUNT &&
  184.                         strcmp(tok,"}"))
  185.                         fileerror("Unknown condition",
  186.                               tok,fp);
  187.                     else if (co != CONDITIONCOUNT) {
  188.                         lk->mask |= 1<<co;
  189.                         if (tok[0] != '!')
  190.                             lk->cond |= 1<<co;
  191.                         }
  192.                     } while(strcmp(tok,"}"));
  193.                 }
  194.             else if (!strcmp(tok,"}")) {
  195.                 donestate = True;
  196.                 }
  197.             }
  198.         }
  199.     else if (!strcmp(tok,"}")) {
  200.         donebrain = True;
  201.         }
  202.     }
  203. }
  204.  
  205. /* think - perform one state transition for this vehicle, based on it's
  206.  * state machine brain.
  207.  */
  208. void think(struct vehicle *v, struct vehicle **vh, struct object **oh)
  209. {
  210. struct state *st = NULL;
  211. int i;
  212. int ln;
  213. int ac;
  214.  
  215. /* find current state pointer.
  216.  */
  217. for(i=0; i<v->stcount; i++)
  218.     if (v->states[i].num == v->currentstate) {
  219.         st = &(v->states[i]);
  220.         break;
  221.         }
  222. if (!st) {
  223.     printf("vehicle %s is in non-existant state %d!\n",v->code,
  224.            v->currentstate);
  225.     printf("resetting to dumb mode\n");
  226.     v->currentstate = -1;
  227.     return;
  228.     }
  229.  
  230. /* perform actions for this state.
  231.  */
  232. for(ac=0; ac < ACTIONCOUNT; ac++)
  233.     if (st->action & (1<<ac)) {
  234.         actionfuncs[ac](v,vh,oh);
  235.         }
  236.  
  237. /* evaluate all links.
  238.  * Algorithm - for each set bit in the mask, set the corresponding bit in
  239.  * the truemask if that condition is true. Then xor the truemask with
  240.  * the conditions, and if the result is zero (all same), take the link.
  241.  */
  242. for(ln=0; ln < st->lcount; ln++) {
  243.     struct link *lk;
  244.     int j;
  245.     long truemask = 0;
  246.  
  247.     lk = &(st->links[ln]);
  248.     for(j=0; j<CONDITIONCOUNT; j++)
  249.         if ((lk->mask & (1<<j)) && conditionfuncs[j](v,vh,oh))
  250.             truemask |= (1<<j);
  251.     if ((truemask ^ lk->cond) == 0) {
  252.         v->currentstate = lk->st;
  253.         /* printf("changing to state %d\n",lk->st); */
  254.         break;
  255.         }
  256.     }
  257.  
  258. /* Reset the bumped flag.
  259.  */
  260. v->bumped = False;
  261. }
  262.  
  263.  
  264. /* objectahead - returns a pointer to the closest object ahead of v, within
  265.  * a 5 degree arc either side of v's current facing. Returns NULL if no
  266.  * object can be found.
  267.  *
  268.  * v        - vehicle doing the looking
  269.  * oh        - head of the object list
  270.  * interesting    - function to determine if an object should condsidered
  271.  */
  272. struct object *objectahead(struct vehicle *v, struct object *oh,
  273.                Bool (*interesting)(struct object *))
  274. {
  275. double mindist = VIEW_RANGE*VIEW_RANGE*2;
  276. struct object *closest = NULL;
  277. struct object *part0;
  278. double dist;
  279.  
  280. part0 = v->parts[0];
  281. while(oh) {
  282.     /* only consider objects closer than the current closest,
  283.      * that are not part of the vehicle doing the looking, and
  284.      * that are judged relevant by the interesting() function.
  285.      */
  286.     if ((dist = objectdist(part0,oh)) < mindist &&
  287.         interesting(oh) && oh->parent != v) {
  288.         double ang;    /* angle to target */
  289.         double vang;    /* heading */
  290.  
  291.         double x,y;
  292.  
  293.         /* compute angle to this object.
  294.          */
  295.         x = oh->pos.y - part0->pos.y;
  296.         y = oh->pos.x - part0->pos.x;
  297.         ang = atan2(y,x);
  298.  
  299.         /* compute sensible vehicle heading */
  300.         vang = v->angle;
  301.         vang = dtor(90.0) - vang;
  302.         while(vang < -PI)
  303.             vang += 2*PI;
  304.         while(vang > PI)
  305.             vang -= 2*PI;
  306.  
  307.         /*
  308.         printf("heading=%f angle=%f xoff=%f yoff=%f\n",
  309.             rtod(vang),rtod(ang),x,y);
  310.         */
  311.         if (dabs(ang - vang) < dtor(5.0)) {
  312.             closest = oh;
  313.             mindist = dist;
  314.             }
  315.         }
  316.     oh = oh->next;
  317.     }
  318.  
  319. /* If a vehicle is found, record it's vid for subsequent above/below/shoot
  320.  * actions.
  321.  */
  322. if (closest && closest->parent)
  323.     v->lastvid = closest->parent->vid;
  324. else
  325.     v->lastvid = -1;
  326. return closest;
  327. }
  328.  
  329. /* objectdist - returns the distance^2 between two objects in the x/y
  330.  * plane.
  331.  */
  332. double objectdist(struct object *ob1, struct object *ob2)
  333. {
  334. double xd, yd;
  335.  
  336. xd = ob1->pos.x - ob2->pos.x;
  337. yd = ob1->pos.y - ob2->pos.y;
  338. return xd*xd + yd*yd;
  339. }
  340.  
  341.  
  342. /*************************************************************************
  343.  * Condition functions
  344.  */
  345. static Bool hplow(struct vehicle *v, struct vehicle **vh, struct object **oh)
  346. {
  347. return (v->hp < 5);
  348. }
  349.  
  350. static Bool ammolow(struct vehicle *v, struct vehicle **vh, struct object **oh)
  351. {
  352. return (v->ammo < 5);
  353. }
  354.  
  355. static Bool threatfar(struct vehicle *v, struct vehicle **vh,
  356.               struct object **oh)
  357. {
  358. struct object *cst;
  359.  
  360. cst = objectahead(v,*oh,isthreat);
  361. return cst != NULL;
  362. }
  363.  
  364. static Bool treefar(struct vehicle *v, struct vehicle **vh, struct object **oh)
  365. {
  366. struct object *cst;
  367.  
  368. cst = objectahead(v,*oh,istree);
  369. return cst != NULL;
  370. }
  371.  
  372. static Bool anyfar(struct vehicle *v, struct vehicle **vh, struct object **oh)
  373. {
  374. struct object *cst;
  375.  
  376. cst = objectahead(v,*oh,isany);
  377. return cst != NULL;
  378. }
  379.  
  380. static Bool threatclose(struct vehicle *v, struct vehicle **vh,
  381.             struct object **oh)
  382. {
  383. struct object *cst;
  384.  
  385. cst = objectahead(v,*oh,isthreat);
  386. return cst && vehicledist(v,cst->parent) < 40*40;
  387. }
  388.  
  389. static Bool treeclose(struct vehicle *v, struct vehicle **vh, struct object **oh)
  390. {
  391. struct object *cst;
  392.  
  393. cst = objectahead(v,*oh,istree);
  394. return cst && vehicledist(v,cst->parent) < 40*40;
  395. }
  396.  
  397. static Bool anyclose(struct vehicle *v, struct vehicle **vh, struct object **oh)
  398. {
  399. struct object *cst;
  400.  
  401. cst = objectahead(v,*oh,isany);
  402. return v->bumped || (cst && objectdist(v->parts[0],cst) < 40*40);
  403. }
  404.  
  405. static Bool underfire(struct vehicle *v, struct vehicle **vh,
  406.               struct object **oh)
  407. {
  408. return v->lasthit >= 0.0 && v->lasthit < 3.0;
  409. }
  410.  
  411. static Bool reload(struct vehicle *v, struct vehicle **vh, struct object **oh)
  412. {
  413. return v->reload > 0;
  414. }
  415.  
  416. static Bool reslow(struct vehicle *v, struct vehicle **vh, struct object **oh)
  417. {
  418. return v->res < 5;
  419. }
  420.  
  421. static Bool moving(struct vehicle *v, struct vehicle **vh, struct object **oh)
  422. {
  423. return dabs(v->velocity) > 1.0;
  424. }
  425.  
  426. static Bool stall(struct vehicle *v, struct vehicle **vh, struct object **oh)
  427. {
  428. return v->velocity < 5.0;
  429. }
  430.  
  431. static Bool altlow(struct vehicle *v, struct vehicle **vh, struct object **oh)
  432. {
  433. return v->parts[0]->pos.z < 10;
  434. }
  435.  
  436. static Bool above(struct vehicle *v, struct vehicle **vh, struct object **oh)
  437. {
  438. struct vehicle *tar;
  439.  
  440. tar = findbyvid(*vh,v->lastvid);
  441. return tar && v->parts[0]->pos.z > tar->parts[0]->pos.z;
  442. }
  443.  
  444. static Bool below(struct vehicle *v, struct vehicle **vh, struct object **oh)
  445. {
  446. struct vehicle *tar;
  447.  
  448. tar = findbyvid(*vh,v->lastvid);
  449. return tar && v->parts[0]->pos.z < tar->parts[0]->pos.z;
  450. }
  451.  
  452. static Bool always(struct vehicle *v, struct vehicle **vh, struct object **oh)
  453. {
  454. return True;
  455. }
  456.  
  457. static Bool prizefar(struct vehicle *v, struct vehicle **vh, struct object **oh)
  458. {
  459. struct object *cst;
  460.  
  461. cst = objectahead(v,*oh,isprize);
  462. return cst != NULL;
  463. }
  464.  
  465. static Bool prizeclose(struct vehicle *v, struct vehicle **vh,
  466.                struct object **oh)
  467. {
  468. struct object *cst;
  469.  
  470. cst = objectahead(v,*oh,isprize);
  471. return cst && vehicledist(v,cst->parent) < 40*40;
  472. }
  473.  
  474. static Bool maybe(struct vehicle *v, struct vehicle **vh, struct object **oh)
  475. {
  476. return rand()%2 == 0;
  477. }
  478.  
  479. static Bool counting(struct vehicle *v, struct vehicle **vh, struct object **oh)
  480. {
  481. return v->ftimer > 0.0;
  482. }
  483.  
  484. static Bool collision(struct vehicle *v, struct vehicle **vh,
  485.               struct object **oh)
  486. {
  487. return v->bumped;
  488. }
  489.  
  490. /************************************************************************
  491.  * action functions
  492.  */
  493. static void noop(struct vehicle *v, struct vehicle **vh, struct object **oh)
  494. {
  495. }
  496.  
  497. static void shoot(struct vehicle *v, struct vehicle **vh, struct object **oh)
  498. {
  499. double turret_ang = 0.0;
  500. struct vehicle *tar;
  501.  
  502. /* Fire only if there is a vehicle in sight, that still exists and
  503.  * that is within the elevation range of the firer's gun.
  504.  */
  505. if (v->lastvid != -1 && (tar = findbyvid(*vh,v->lastvid))) {
  506.     turret_ang = atan2(heightdiff(tar,v),sqrt(vehicledist(tar,v)));
  507.     if (dabs(turret_ang) < v->max.turret_ang) {
  508.         /* printf("firing at %s\n",tar->code); */
  509.         fire(vh,oh,v);
  510.         }
  511.     }
  512. }
  513.  
  514. static void stop(struct vehicle *v, struct vehicle **vh, struct object **oh)
  515. {
  516. v->angle_vel = 0;
  517. v->velocity  = 0;
  518. v->climb     = 0;
  519. }
  520.  
  521. static void accel(struct vehicle *v, struct vehicle **vh, struct object **oh)
  522. {
  523. if (v->velocity < v->max.velocity)
  524.     v->velocity += DELTA_VELOCITY;
  525. }
  526.  
  527. static void decel(struct vehicle *v, struct vehicle **vh, struct object **oh)
  528. {
  529. if (v->velocity > -(v->max.velocity))
  530.     v->velocity -= DELTA_VELOCITY;
  531. }
  532.  
  533. static void left(struct vehicle *v, struct vehicle **vh, struct object **oh)
  534. {
  535. rotatevehicle(v,v->angle - dtor(5.0));
  536. }
  537.  
  538. static void right(struct vehicle *v, struct vehicle **vh, struct object **oh)
  539. {
  540. rotatevehicle(v,v->angle + dtor(5.0));
  541. }
  542.  
  543. static void climb(struct vehicle *v, struct vehicle **vh, struct object **oh)
  544. {
  545. }
  546.  
  547. static void dive(struct vehicle *v, struct vehicle **vh, struct object **oh)
  548. {
  549. }
  550.  
  551. static void detonate(struct vehicle *v, struct vehicle **vh, struct object **oh)
  552. {
  553. v->hp = -1;
  554. }
  555.  
  556. static void wall(struct vehicle *v, struct vehicle **vh, struct object **oh)
  557. {
  558. }
  559.  
  560. static void mine(struct vehicle *v, struct vehicle **vh, struct object **oh)
  561. {
  562. }
  563.  
  564. static void gunsite(struct vehicle *v, struct vehicle **vh, struct object **oh)
  565. {
  566. }
  567.  
  568. static void starttimer(struct vehicle *v, struct vehicle **vh,
  569.                struct object **oh)
  570. {
  571. v->ftimer += 5.0;
  572. }
  573.  
  574. /* example brain for gunsite
  575. brain {
  576.     state 1 {
  577.         action left 
  578.         link 2 { threatfar }
  579.         }
  580.     state 2 {
  581.         action fire
  582.         action something
  583.         link 1 { !threatfar }
  584.         }
  585.     }
  586. */
  587.  
  588. static Bool isthreat(struct object *o)
  589. {
  590. return o->parent && (o->parent->owner == o_player ||
  591.        o->parent->owner == o_network || o->parent->type == t_gunsite);
  592. }
  593.  
  594. static Bool istree(struct object *o)
  595. {
  596. return o->parent && o->parent->type == t_tree;
  597. }
  598.  
  599. static Bool isany(struct object *o)
  600. {
  601. return !o->parent || !(o->parent->type == t_scenery ||
  602.        o->parent->type == t_bullet || o->parent->type == t_missile ||
  603.        o->parent->type == t_shrapnel);
  604. }
  605.  
  606. static Bool isprize(struct object *o)
  607. {
  608. return o->parent && (o->parent->type == t_weapon ||
  609.        o->parent->type == t_munitions);
  610. }
  611.  
  612.